// =======================================================================
// 
//       Filename:  citerator.hpp
// 
//    Description:  
// 
//        Version:  1.0
//        Created:  25.03.2010 21:46:26
//       Revision:  none
//       Compiler:  g++
// 
//         Author:  Dominik 'domachine' Burgdörfer (-), dominik.burgdoerfer@googlemail.com
//        Company:  -
// 
// =======================================================================


#ifndef  CITERATOR_INC
#define  CITERATOR_INC
#include <stdexcept>
#include <vector>
#include <iostream>
#ifdef DEBUG
    #define DBG(msg) std::cerr << __FILE__ << ":" \
        << __LINE__ << ": " \
        << msg << std::endl;
#else
    #define DBG
#endif

namespace webplodder {
    /**
     * @brief This class provides an interface
     * to read files and having access to the previous
     * read and the following character.
     */
    class CIterator {
    public:
        CIterator();
        CIterator(std::istream& stream);
        CIterator(const CIterator& other);

        /**
         * @brief Move the file pointer forward.
         */
        CIterator& moveForward();

        /**
         * @brief Returns the current char in the
         * middle of the buffer.
         */
        char currentChar();

        /**
         * @brief Returns the char which will be
         * the next under the file pointer.
         */
        char nextChar();

        /**
         * @brief Returns the char before the
         * current char.
         */
        char lastChar();

        /**
         * @brief Delegates the good() method
         * of the underlaying std::istream.
         */
        bool good() const;

        /**
         * @brief Delegates the eof() method
         * of the underlaying std::istream.
         */
        bool eof() const;

        /**
         * @brief Returns the current position
         * of the file pointer.
         */
        long position() const;

        /**
         * @brief Rewinds the underlaying std::istream.
         */
        void rewind();

        /**
         * @brief Sets the underlaying stream.
         */
        void setStream(std::istream& stream);

    private:
        void readNextChar();
        void updateCache(char ch);
        void resetCache();

        std::istream* mStream;
        long mPosition;
        char mCache[3];
        long mCachePos[3];
    };
}
#endif   // ----- #ifndef CITERATOR_INC  -----
